from machine import Pin
import uasyncio as asyncio
from time import sleep_ms
from tm1637 import TM1637

class KeyBoard:
    
    KEY_LED_OUT = 0x01
    KEY_LED_POWER = 0x02
    KEY_LED_UP = 0x04
    KEY_LED_MODE = 0x08
    KEY_LED_SET = 0x10
    KEY_LED_DOWN = 0x20
    KEY_LED_LIGHT = 0x40
    

    def __init__(self, slk, dio, key_press_cb=None):
        print("-" * 36)
        print("init KeyBoard...")
        self.slk = slk
        self.dio = dio
        self.key_press_cb = key_press_cb
        self.last_key = 0
        self.tm1637 = TM1637(Pin(self.slk, Pin.OUT), Pin(self.dio, Pin.OUT))
        self.led_state = bytearray(1)
        self.led_state[0] = 0x00
        self.led_info = [
            {"name":"light", "mode":"normal", "status": False, "index": 6, "turn_loop": 10, "loop_count": 0},
            {"name":"down", "mode":"normal", "status": False, "index": 5, "turn_loop": 10, "loop_count": 0},
            {"name":"set", "mode":"normal", "status": False, "index": 4, "turn_loop": 10, "loop_count": 0},
            {"name":"mode", "mode":"normal", "status": False, "index": 3, "turn_loop": 10, "loop_count": 0},
            {"name":"up", "mode":"normal", "status": False, "index": 2, "turn_loop": 10, "loop_count": 0},
            {"name":"power", "mode":"flash", "status": False, "index": 1, "turn_loop": 10, "loop_count": 0},
            {"name":"out", "mode":"static", "status": False, "index": 0, "turn_loop": 0, "loop_count": 0}
        ]
        asyncio.create_task(self.loop_scan_key_press())
        print("-" * 36)
        #self.loop_scan_key_press()
        
        #while True:
        #    utime.sleep_ms(1000)
        
    def pre_led_light_process(self):
        # process led_out
        for led in self.led_info:
            led["loop_count"] = led["loop_count"] + 1
            if led["mode"] == "static":
                led["loop_count"] = 0
                continue
            elif led["mode"] == "flash":
                if led["loop_count"] > led["turn_loop"]:
                    led["status"] = not led["status"]
                    led["loop_count"] = 0
            elif led["mode"] == "normal":
                if led["status"] == True:
                    if led["loop_count"] > led["turn_loop"]:
                        led["status"] = not led["status"]
                        led["loop_count"] = 0
                else:
                    led["loop_count"] = 0
                    
        self.build_ledstate_from_ledInfo()
        
    def build_ledstate_from_ledInfo(self):
        self.led_state[0] = 0x00
        #print("before build for led_status:", bin(self.led_state[0]))
        for led in self.led_info:
            if led["status"] == True:
                self.led_state[0] |= (1 << led["index"])
        #print("after build for led_status:", bin(self.led_state[0]))

    
    def pre_keypress_process(self, key):
        if key != 255:
            # print("key:", key)
            if key == 247 :
                self.led_info[6]["status"] = True
            elif key == 246 :
                self.led_info[5]["status"] = True
            elif key == 245 :
                self.led_info[4]["status"] = True
            elif key == 244 :
                self.led_info[3]["status"] = True
            elif key == 243 :
                self.led_info[2]["status"] = True
            elif key == 242 :
                self.led_info[1]["status"] = True
            elif key == 241 :
                self.led_info[0]["status"] = True
            
            if self.key_press_cb:
                self.key_press_cb(self.convert_keycode_to_keyname(key))
                
    def convert_keycode_to_keyname(self, keycode):
        if keycode == 247:
            return "KEY_OUT"
        elif keycode == 246:
            return "KEY_POWER"
        elif keycode == 245:
            return "KEY_UP"
        elif keycode == 244:
            return "KEY_MODE"
        elif keycode == 243:
            return "KEY_SET"
        elif keycode == 242:
            return "KEY_DOWN"
        elif keycode == 241:
            return "KEY_LIGHT"
         
    def change_led_mode(self, key, mode, status):
        if key not in ["out", "power", "up", "mode", "set", "down", "light"]:
            return
        if mode not in ["normal", "flash", "static"]:
            return
        if key == "light":
            self.led_info[0]["mode"] = mode
            self.led_info[0]["status"] = True if status else False
        elif key == "down":
            self.led_info[1]["mode"] = mode
            self.led_info[1]["status"] = True if status else False
        elif key == "set":
            self.led_info[2]["mode"] = mode
            self.led_info[2]["status"] = True if status else False
        elif key == "mode":
            self.led_info[3]["mode"] = mode
            self.led_info[3]["status"] = True if status else False
        elif key == "up":
            self.led_info[4]["mode"] = mode
            self.led_info[4]["status"] = True if status else False  
        elif key == "power":
            self.led_info[5]["mode"] = mode
            self.led_info[5]["status"] = True if status else False
        elif key == "out":
            self.led_info[6]["mode"] = mode
            self.led_info[6]["status"] = True if status else False

    
    async def loop_scan_key_press(self):
        while True:
            try:
                self.pre_led_light_process()
                # print(self.led_state)
                self.tm1637.write(self.led_state, 5)
                sleep_ms(10)
                key = self.tm1637.read_key()
                self.pre_keypress_process(key)
            except Exception as e:
                print("keyBoard loop scan key press error:", e)
            await asyncio.sleep(0.1)
            
    

async def loop():
    while True:
        await asyncio.sleep(1)
                
if __name__ == "__main__":
    ### gpio 34-39 can't used switch
    slk = 12
    dio = 13
    
    def key_press_callback(key_name):
        print(f"{key_name} pressed")
    kb = KeyBoard(slk, dio, key_press_callback)
    
    try:
        asyncio.run(loop())
    except KeyboardInterrupt:
        print('Interrupted')
    finally:
        asyncio.new_event_loop()
        
    
    
    